/*
 * DatagramBuilder Library: serialize/deserialize data to/from datagram
 * Copyright (C) 2008 Rakov Ilya <RakovIlya@gmail.com>
 *
 * This library can be distributed under the terms of the GNU LGPLv2.
 * See the file COPYING.LIB.
 */


#ifndef DATAGRAM_MARKIMPL_H_
#define DATAGRAM_MARKIMPL_H_


/**
 * @file MarkImpl.h
 *
 * @brief Mark implementation file
 *
 * @date Dec 2, 2008
 * @author Rakov Ilya
 */


template < class T >
Mark<T>::Mark()
  : container_( false ) // not initialized container
{
}


template < class T >
Mark<T>::Mark( const T &value )
  : container_( false ), // not initialized container
    value_   ( value )
{
}


template < class T >
void Mark<T>::Set( const T &value )
{
  if ( IsBinded() )
    container_.SerializeValue( value, offset_ );
  else
    value_ = value;
}

template < class T >
const T& Mark<T>::Get() const
{
  if ( IsBinded() )
    container_.DeSerializeValue( value_, offset_ );

  return value_;
}


template < class T >
void Mark<T>::Bind( const Builder &builder ) const
{
  Bind( builder.container_, builder.GetSize() );
}


template < class T >
void Mark<T>::Bind( const Parser &parser ) const
{
  Bind( parser.container_, parser.transactNext_ );
}


template < class T >
void Mark<T>::Bind( const Container &container, size_t offset ) const
{
  offset_    = offset;
  container_ = container;
}


template < class T >
bool Mark<T>::IsBinded() const
{
  return container_.IsInitialized();
}


template < class T >
bool Mark<T>::operator ==( const Mark &other ) const
{
  return Get() == other.Get();
}


template < class T >
bool Mark<T>::operator !=( const Mark &other ) const
{
  return !(*this == other);
}


template< class T >
Mark< T > mark( const T &value )
{
  return Mark< T >( value );
}


template< class CharType, class CharTrait, class T >
std::basic_ostream< CharType, CharTrait >&
operator <<( std::basic_ostream<CharType, CharTrait> &out, const Mark<T> &obj )
{
  out << "mark(" << obj.Get()
      << (
            obj.IsBinded() ? ")"
                            : ")-not binded"
         );

  return out;
}


template < class T >
struct SerializeImpl< Mark< T > >
{

  static inline void SerializeTag( Builder &builder )
  {
    SerializeImpl< T >::SerializeTag( builder );
  }


  static inline void Serialize( Builder &builder, const Mark< T > &mark )
  {
    T tmp( mark.Get() );

    mark.Bind( builder );

    SerializeImpl< T >::Serialize( builder, tmp );
  }


  static inline void DeSerializeTag( Parser &parser )
  {
    SerializeImpl< T >::DeSerializeTag( parser );
  }


  static inline void DeSerialize( Parser &parser, Mark< T > &mark )
  {
    mark.Bind( parser );

    T tmp;

    SerializeImpl< T >::DeSerialize( parser, tmp ); // just skip
  }

};


#endif /* DATAGRAM_MARKIMPL_H_ */
